/***************************************************************************
* Copyright  Faraday Technology Corp 2002-2003.  All rights reserved.      *
*--------------------------------------------------------------------------*
* Name:interrupt.c                                                         *
* Description: Interrupt library routine                                   *
* Author:                         																				 *
****************************************************************************/
#include "unione_lite.h"
#include "interrupt.h"
#include "DrvUART010.h"
extern int is_enter_irq;

void fLib_ClearInt(UINT32 IntNum)
{
	//fLib_printf("fLib_ClearInt\n");	
	if(IntNum < 64)
	{				
		ClearIRQStatus(IntNum);	
	}
}

void fLib_EnableInt(UINT32 IntNum)
{
	if(IntNum < 64)	
	{
		IRQSources |= ((UINT32)1 << IntNum);
		UnmaskIRQ(IntNum);
	}
}

void fLib_DisableInt(UINT32 IntNum)
{
	if(IntNum < 64)	
	{
		MaskIRQ(IntNum);
		IRQSources &= ~(1 << IntNum);
	}  
}
/**
intMode 	0  	level
intMode 	1 	edge
intLevel  	0	high
intLevel  	1	low
**/
void fLib_SetIntTrig(UINT32 IntNum,int intMode,int intLevel)
{
	if(IntNum < 64)	
	{
		SetIRQmode(IntNum ,intMode);
		SetIRQlevel(IntNum,intLevel); 
	}
}

/*
 * Routine to check and install requested interrupt. Just sets up logical
 * structures, doesn't alter interrupts at all.
 */
UINT32 fLib_ConnectInt(UINT32 IntNum, PrVoid Handler)
{
	fLib_INT *Irq;		
	
	
	if(IntNum < 64)	
	{	    
	  if (!Handler)
	    return false;

	  Irq = &IRQVector[IntNum];
	  Irq->Handler = Handler;   
	  Irq->IntNum=IntNum;
	}
	fLib_printf("%s:handler=%x,IntNum=%d\n",__FUNCTION__,IRQVector[IntNum],IntNum);	
  return true;
}


/* Call this routine before trying to change the routine attached to an IRQ */
UINT32 fLib_CloseInt(UINT32 IntNum)
{
	if(IntNum < 64)	
	{		
	  IRQVector[IntNum].Handler = (PrVoid) 0;
	  IRQVector[IntNum].IntNum =  0;
	}
	
	return true;
}

/* Initialise the IRQ environment without installing interrupt handlers. */
void fLib_ResetInterrupts()
{
    int i;     

    /* Mask out all interrupt sources. */
    for (i = 0; i < PLATFORM_IRQ_TOTALCOUNT; i++)
    {	
    	MaskIRQ(i); 
        IRQVector[i].IntNum = 0;
        IRQVector[i].Handler = (PrVoid) 0;      
    }		 		
}

/*************************************/
/* Start of Vector-related functions */
/*************************************/
UINT32 fLib_ConnectVectorInt(UINT32 IntNum, UINT32 Handler)
{
		UINT32 i, vacancy = NR_VECT;	  
  
	if(IntNum >= 64)	
		return false;	
	
	/* Check if the interrupt has been registered as vector one and 
	 * search for a vacancy simultaneously
	 */	
	for(i=0; i<NR_VECT; i++)
	{
		if(!GetVectAddr(i))		
		{
			if(vacancy == NR_VECT) vacancy = i;
		}
		else if(IntNum == (GetVectAddrCtrl(i) & 0x3F))
		{
			return false;
		}	
	}				
    
	/* Check if a vacancy has been found */
	if(vacancy == NR_VECT) return false;
	
	SetVectAddr(vacancy, Handler);		
	SetVectAddrCtrl(vacancy, IntNum|VECT_IRQ_SRC_EN);	 	
//	printf("vacancy = %d , Handler = %x\n",vacancy,Handler);
  
  return true;
}

UINT32 fLib_CloseVectorInt(UINT32 IntNum)
{  	
	UINT32 i;
	
	if(IntNum >= 64)	
		return false;
		
	/* Check if the interrupt is vector one */		
	for(i=0; i<NR_VECT; i++)
	{
		if(GetVectAddr(i) && IntNum == (GetVectAddrCtrl(i) & 0x3F)) break;		
	}

	if(i == NR_VECT) return false;	
	
	SetVectAddr(i, 0x0);		
	SetVectAddrCtrl(i, 0x0);		

  return true;
}

void fLib_EnableVectorInt(void)
{	
	EnableVectInt();	
}

void fLib_DisableVectorInt(void)
{	
	DisableVectInt();	
}

/* Called once on start-up to initialise data structures & interrupt routines */
void fLib_Int_Init()
{
	UINT32 i;
	

        fLib_DisableVectorInt();

	for(i=0; i<NR_VECT; i++)
	{
		SetVectAddr(i, 0x0);
		SetVectAddrCtrl(i, 0x0);
	}
				
	SetDefVectAddr((UINT32)DispatchIRQ);			
	fLib_EnableVectorInt();
	fLib_ResetInterrupts();    
}
int is_irq_contex(void)
{
    return is_enter_irq;
    //return 0;
}


/* End of Vector-related functions */
